/*
 * @Author: LVGRAPE
 * @Date: 2023-08-31 09:17:30
 * @LastEditTime: 2025-04-09 19:49:04
 * @LastEditors: LVGRAPE
 * @Description:
 * @FilePath: \ZINO_FC_V4\ZINO\hardware\i2c\i2c_device_search.c
 * 可以输入预定的版权声明、个性签名、空行等
 */
#include <rtthread.h>
#include <rtdevice.h>
#include "zino.h"
#define DBG_TAG "zino_i2c"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>

/**
 * @brief Try to access i2c device
 *
 * @param i2cbusname
 * @param addr
 * @return rt_size_t 0:fail, 1:success
 */
rt_size_t i2c_device_try(const char *i2cbusname, uint8_t addr)
{
    rt_size_t ret = 0;
    struct rt_i2c_bus_device *i2cbus = (struct rt_i2c_bus_device *)rt_device_find(i2cbusname);
    if (i2cbus != RT_NULL)
    {
        i2cbus->retries = 1;

        struct rt_i2c_msg msgs;
        msgs.addr = addr;
        msgs.flags = RT_I2C_WR;
        msgs.buf = NULL;
        msgs.len = 0;
        ret = rt_i2c_transfer(i2cbus, &msgs, 1);
        struct rt_i2c_bit_ops *ops = (struct rt_i2c_bit_ops *)i2cbus->priv;
        ops->delay_us = 0;
        // LOG_D("Try:%s addr:0x%02X, ret:%d \n", i2cbusname, addr, ret);
    }
    else
    {
        LOG_E("Not found %s on system!\n", i2cbusname);
    }
    return ret;
}
rt_size_t i2c_device_scan(const char *i2cbusname)
{
    rt_size_t deviceCnt = 0;
    rt_uint8_t *devicelist = rt_malloc(0x7f);
    LOG_I("%s scanning...\n", i2cbusname);
    for (uint8_t addr = 0x01; addr < 0x7f; addr++)
    {
        uint8_t ret = i2c_device_try(i2cbusname, addr);
        if (ret == 1)
        {
            devicelist[deviceCnt] = addr;
            deviceCnt++;
        }
        else if (ret == 0)
        {
            break;
        }
        else
        {
            // LOG_D("Try:%s addr:0x%02X, ret:%d \n", i2cbusname, addr, ret);
        }
        rt_thread_delay(5);
    }
    LOG_I("%s scan done, %d device found.\n", i2cbusname, deviceCnt);
    for (uint8_t i = 0; i < deviceCnt; i++)
    {
        LOG_I("* Device:0x%02X\n", devicelist[i]);
    }
    rt_free(devicelist);
    return deviceCnt;
}
long i2c1_scan(void)
{
    return i2c_device_scan("i2c1");
}
long i2c2_scan(void)
{
    return i2c_device_scan("i2c2");
    ;
}
MSH_CMD_EXPORT(i2c1_scan, i2c1 scan);
MSH_CMD_EXPORT(i2c2_scan, i2c2 scan);
